﻿
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;


namespace Organized
{
    public class SkyBox : Drawable3dComponent
    {
        private VertexPositionNormalTexture[] cubeVertices;
        private VertexBuffer vertexBuffer;
        private TextureCube texture;
        private Effect effect;

        private Effect DepthEffect;
        private Effect SkyEffect;

        Camera camera;

        private float RotationV = 0;
        private bool enableFog;

        public virtual Matrix WorldMatrix
        {
            get { return worldMatrix; }
            set { worldMatrix = value; }
        }
        Matrix worldMatrix = Matrix.Identity;

        Vector4 BottomColor = new Vector4(0.0f, 0.0f, 0.0f, 1.0f);
        Vector4 TopColor = new Vector4(0.8f, 0.3f, 0.9f, 1.0f);

        public SkyBox(Lighting _light, Vector3 _position, GameScreen Parent) : base(_light, _position, Parent)
        {
            texture =  Engine.Content.Load<TextureCube>("Content/Textures/OutputCube");
            SkyEffect = Engine.Content.Load<Effect>("Content/Effects/SkyBox");
            DepthEffect = Engine.Content.Load<Effect>("Content/Effects/modelShader");
            effect = SkyEffect;
            camera = Engine.Services.GetService<Camera>();
            cubeVertices = new VertexPositionNormalTexture[36];

            Vector3 topLeftFront = new Vector3(-1.0f, 1.0f, 1.0f);
            Vector3 bottomLeftFront = new Vector3(-1.0f, -1.0f, 1.0f);
            Vector3 topRightFront = new Vector3(1.0f, 1.0f, 1.0f);
            Vector3 bottomRightFront = new Vector3(1.0f, -1.0f, 1.0f);
            Vector3 topLeftBack = new Vector3(-1.0f, 1.0f, -1.0f);
            Vector3 topRightBack = new Vector3(1.0f, 1.0f, -1.0f);
            Vector3 bottomLeftBack = new Vector3(-1.0f, -1.0f, -1.0f);
            Vector3 bottomRightBack = new Vector3(1.0f, -1.0f, -1.0f);

            Vector2 textureTopLeft = new Vector2(1.0f, 1.0f);
            Vector2 textureTopRight = new Vector2(0.0f, 1.0f);
            Vector2 textureBottomLeft = new Vector2(1.0f, 0.0f);
            Vector2 textureBottomRight = new Vector2(0.0f, 0.0f);

            Vector3 frontNormal = new Vector3(0.0f, 0.0f, 1.0f);
            Vector3 backNormal = new Vector3(0.0f, 0.0f, -1.0f);
            Vector3 topNormal = new Vector3(0.0f, 1.0f, 0.0f);
            Vector3 bottomNormal = new Vector3(0.0f, -1.0f, 0.0f);
            Vector3 leftNormal = new Vector3(-1.0f, 0.0f, 0.0f);
            Vector3 rightNormal = new Vector3(1.0f, 0.0f, 0.0f);

            // Front face
            cubeVertices[0] =
                new VertexPositionNormalTexture(
                topLeftFront, frontNormal, textureTopLeft);
            cubeVertices[1] =
                new VertexPositionNormalTexture(
                bottomLeftFront, frontNormal, textureBottomLeft);
            cubeVertices[2] =
                new VertexPositionNormalTexture(
                topRightFront, frontNormal, textureTopRight);
            cubeVertices[3] =
                new VertexPositionNormalTexture(
                bottomLeftFront, frontNormal, textureBottomLeft);
            cubeVertices[4] =
                new VertexPositionNormalTexture(
                bottomRightFront, frontNormal, textureBottomRight);
            cubeVertices[5] =
                new VertexPositionNormalTexture(
                topRightFront, frontNormal, textureTopRight);

            // Back face 
            cubeVertices[6] =
                new VertexPositionNormalTexture(
                topLeftBack, backNormal, textureTopRight);
            cubeVertices[7] =
                new VertexPositionNormalTexture(
                topRightBack, backNormal, textureTopLeft);
            cubeVertices[8] =
                new VertexPositionNormalTexture(
                bottomLeftBack, backNormal, textureBottomRight);
            cubeVertices[9] =
                new VertexPositionNormalTexture(
                bottomLeftBack, backNormal, textureBottomRight);
            cubeVertices[10] =
                new VertexPositionNormalTexture(
                topRightBack, backNormal, textureTopLeft);
            cubeVertices[11] =
                new VertexPositionNormalTexture(
                bottomRightBack, backNormal, textureBottomLeft);

            // Top face
            cubeVertices[12] =
                new VertexPositionNormalTexture(
                topLeftFront, topNormal, textureBottomLeft);
            cubeVertices[13] =
                new VertexPositionNormalTexture(
                topRightBack, topNormal, textureTopRight);
            cubeVertices[14] =
                new VertexPositionNormalTexture(
                topLeftBack, topNormal, textureTopLeft);
            cubeVertices[15] =
                new VertexPositionNormalTexture(
                topLeftFront, topNormal, textureBottomLeft);
            cubeVertices[16] =
                new VertexPositionNormalTexture(
                topRightFront, topNormal, textureBottomRight);
            cubeVertices[17] =
                new VertexPositionNormalTexture(
                topRightBack, topNormal, textureTopRight);

            // Bottom face 
            cubeVertices[18] =
                new VertexPositionNormalTexture(
                bottomLeftFront, bottomNormal, textureTopLeft);
            cubeVertices[19] =
                new VertexPositionNormalTexture(
                bottomLeftBack, bottomNormal, textureBottomLeft);
            cubeVertices[20] =
                new VertexPositionNormalTexture(
                bottomRightBack, bottomNormal, textureBottomRight);
            cubeVertices[21] =
                new VertexPositionNormalTexture(
                bottomLeftFront, bottomNormal, textureTopLeft);
            cubeVertices[22] =
                new VertexPositionNormalTexture(
                bottomRightBack, bottomNormal, textureBottomRight);
            cubeVertices[23] =
                new VertexPositionNormalTexture(
                bottomRightFront, bottomNormal, textureTopRight);

            // Left face
            cubeVertices[24] =
                new VertexPositionNormalTexture(
                topLeftFront, leftNormal, textureTopRight);
            cubeVertices[25] =
                new VertexPositionNormalTexture(
                bottomLeftBack, leftNormal, textureBottomLeft);
            cubeVertices[26] =
                new VertexPositionNormalTexture(
                bottomLeftFront, leftNormal, textureBottomRight);
            cubeVertices[27] =
                new VertexPositionNormalTexture(
                topLeftBack, leftNormal, textureTopLeft);
            cubeVertices[28] =
                new VertexPositionNormalTexture(
                bottomLeftBack, leftNormal, textureBottomLeft);
            cubeVertices[29] =
                new VertexPositionNormalTexture(
                topLeftFront, leftNormal, textureTopRight);

            // Right face 
            cubeVertices[30] =
                new VertexPositionNormalTexture(
                topRightFront, rightNormal, textureTopLeft);
            cubeVertices[31] =
                new VertexPositionNormalTexture(
                bottomRightFront, rightNormal, textureBottomLeft);
            cubeVertices[32] =
                new VertexPositionNormalTexture(
                bottomRightBack, rightNormal, textureBottomRight);
            cubeVertices[33] =
                new VertexPositionNormalTexture(
                topRightBack, rightNormal, textureTopRight);
            cubeVertices[34] =
                new VertexPositionNormalTexture(
                topRightFront, rightNormal, textureTopLeft);
            cubeVertices[35] =
                new VertexPositionNormalTexture(
                bottomRightBack, rightNormal, textureBottomRight);

            vertexBuffer = new VertexBuffer(
                Engine.GraphicsDevice,
                VertexPositionNormalTexture.SizeInBytes * cubeVertices.Length, BufferUsage.None);

            vertexBuffer.SetData<VertexPositionNormalTexture>(cubeVertices);

            
            

        }


        public override void DrawDepthMap()
        {

            SetupEffect("DepthMap");
            DrawBox();

        }

        public override void Draw()
        {

            //add me to the component render list, for postproceccing a depthmap
            this.Parent.DrawableRenderList.Add(this);

            SetupEffect("SkyBox");
            enableFog = Engine.GraphicsDevice.RenderState.FogEnable;
            Engine.GraphicsDevice.RenderState.FogEnable = false;
            DrawBox();
            Engine.GraphicsDevice.RenderState.FogEnable = enableFog;
        }


        public void SetupEffect(string technique)
        {
            

            if (technique == "SkyBox")
            {
                
                effect = SkyEffect;
                WorldMatrix = Matrix.CreateTranslation(Position) * Matrix.CreateScale(Scale)  * Matrix.CreateTranslation(camera.Position);
                effect.Parameters["WorldViewProjection"].SetValue(WorldMatrix * camera.View * camera.Projection);                     
                effect.Parameters["textureDiffuse"].SetValue(texture);
                effect.Parameters["xTopColor"].SetValue(TopColor);
                effect.Parameters["xBottomColor"].SetValue(BottomColor);

            }
            if (technique == "DepthMap")
            {
                effect = DepthEffect;
                effect.Parameters["xView"].SetValue(camera.View);
                effect.Parameters["xProjection"].SetValue(camera.Projection);
                effect.Parameters["xWorld"].SetValue(WorldMatrix);  
            }

            effect.CurrentTechnique = effect.Techniques[technique];
        }
        private int counter = 1;
        public override void Update()
        {
           // Rotation =  Matrix.CreateRotationY((float)((Math.PI/960)*counter++)) ;
            base.Update();
        }

        public void DrawBox()
        {
            Engine.GraphicsDevice.VertexDeclaration = new VertexDeclaration(
               Engine.GraphicsDevice,
               VertexPositionNormalTexture.VertexElements);

           

            effect.Begin();

            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                pass.Begin();

                Engine.GraphicsDevice.Vertices[0].SetSource(vertexBuffer, 0, VertexPositionNormalTexture.SizeInBytes);

                Engine.GraphicsDevice.DrawPrimitives(
                    PrimitiveType.TriangleList,
                    0,
                    12
                );

                pass.End();
            }

            effect.End();

            
           
        }

    
    }
}
